package com.xavier.dong.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Arrays;

/**
 * Scattering： 将数据写入到 Buffer时，可以采用 Buffer 时，依次写入  【分散】
 * Gathering： 从 Buffer 读取数据时，也可采用 Buffer 数组，依次 读 【聚合】
 *
 * @author XavierDong
 **/
public class ScatteringAndGathering {


    public static void main(String[] args) {

        // 使用 ServerSocketChannel 和 SocketChannel

        try {
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

            InetSocketAddress inetSocketAddress = new InetSocketAddress(7000);

            // 绑定端口 到 socket 并启动
            serverSocketChannel.socket().bind(inetSocketAddress);

            // 创建一个 Buffer 数组
            ByteBuffer[] byteBuffers = new ByteBuffer[2];
            byteBuffers[0] = ByteBuffer.allocate(5);
            byteBuffers[1] = ByteBuffer.allocate(3);

            // 等待客户端 连接
            SocketChannel socketChannel = serverSocketChannel.accept();

            int messageLength = 8; // 假定 从客户端 接收 8个字节

            // 循环的读取
            while (true) {
                int byteRead = 0;
                while (byteRead < messageLength) {

                    long read = socketChannel.read(byteBuffers);
                    byteRead += read; // 累计读取的 字节数
                    System.out.println("byteRead= " + byteRead);
                    // 输出 使用 流 打印 看看当前的 buffer的 position 和 limit
                    Arrays.asList(byteBuffers).stream().map(buffer -> "position = " + buffer.position() + ", limit= " + buffer.limit()).forEach(System.out::println);


                }

                // 将 所有的 Buffer 进行 flip()
                Arrays.asList(byteBuffers).forEach(ByteBuffer::flip);

                // 将 数据 读出 显示到 客户端
                long byteWrite = 0;
                while (byteWrite < messageLength) {
                    long write = socketChannel.write(byteBuffers);
                    byteWrite += write;
                }

                // 将所有的 Buffer 进行 clear 操作
                Arrays.asList(byteBuffers).forEach(ByteBuffer::clear);

                System.out.println("byteRead= " + byteRead + " byteWrite= " + byteWrite + " messageLength= " + messageLength);
            }


        } catch (IOException e) {
            e.printStackTrace();
        }


    }

}
